package controller;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;

import view.GameHandler;
import view.MenuHandler;
import view.ScreenHandler;


public class TunnelShift extends Applet implements Observer{

	/**
	 * 
	 */
	private static final long serialVersionUID = 546025911444910614L;
	private static int width=400;
	private static int height=400;
	
	Image offscreen; 
    Graphics bufferGraphics;
    ScreenHandler activeScreenHandler;
    Map<String, ScreenHandler> handlers = new HashMap<String, ScreenHandler>();
    Timer rt;
	
	@Override
	public void init() {
		// loade differentes choses au lancement de l' application. une fois fait, elle lance la commande start()

	    setSize( width, height );
	    setVisible( true );
        setBackground(Color.black);
        offscreen = createImage(this.getWidth(),this.getHeight());
        bufferGraphics = offscreen.getGraphics();  
		
	}
	
	@Override
	public void start() {
		
		//creates the menu handler
		MenuHandler menuh = MenuHandler.getInstance(this);
		menuh.addObserver(this);
		addKeyListener(menuh);
		addMouseListener(menuh);
		addMouseMotionListener(menuh);
		handlers.put("menu",menuh);
		
		
		//creates the game handler
		GameHandler gameh = GameHandler.getInstance(this);
		gameh.addObserver(this);
		handlers.put("game",gameh);
		
		activeScreenHandler = menuh;
		rt=new Timer();
		rt.scheduleAtFixedRate(new RenderingTask(), 1000/25, 1000/25);

	}
	

	@Override
	public void update(Graphics g) {
		// 
		paint(g);
	}
	
	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		if(activeScreenHandler!=null){
			activeScreenHandler.paint(offscreen);
		}
		g.drawImage(offscreen,0,0,this);
	}

	@Override
	public void update(Observable Obs, Object event) {
		
		activeScreenHandler.stop();
		
		if(event.equals(Events.START_GAME)){
			removeAllListeners();
			GameHandler gameh = (GameHandler)handlers.get("game");
			addKeyListener(gameh);
			activeScreenHandler=gameh;
		}else if(event.equals(Events.GAME_OVER)){
			removeAllListeners();
			MenuHandler menuh = (MenuHandler)handlers.get("menu");
			addKeyListener(menuh);
			addMouseListener(menuh);
			addMouseMotionListener(menuh);
			activeScreenHandler=menuh;
		}else if(event.equals(Events.QUIT_GAME)){
			for (ScreenHandler sh : handlers.values()) {
				sh.reset();
			}
		}
		activeScreenHandler.reset();
		activeScreenHandler.start();
	}
	
	private void removeAllListeners(){
		for(KeyListener kl:getKeyListeners()){
			removeKeyListener(kl);
		}
		for(MouseListener ml:getMouseListeners()){
			removeMouseListener(ml);
		}
		for(MouseMotionListener mml:getMouseMotionListeners()){
			removeMouseMotionListener(mml);
		}
		for(MouseWheelListener mwl:getMouseWheelListeners()){
			removeMouseWheelListener(mwl);
		}
	}
	
	private class RenderingTask extends TimerTask{
		
		public void run() {
			// TODO Auto-generated method stub
			try{
				update(getGraphics());
			}catch(Exception e){
				
			}
		}
	}
}
